<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.3.1"/>
<title>libnetconf: transAPI Tutorial</title>
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<link href="../../navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../resize.js"></script>
<script type="text/javascript" src="../../navtree.js"></script>
<script type="text/javascript">
  $(document).ready(initResizable);
  $(window).load(resizeHeight);
</script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/javascript">
  $(document).ready(function() { searchBox.OnSelectItem(0); });
</script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../libnetconf-logo.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">libnetconf
   &#160;<span id="projectnumber">0.6.0</span>
   </div>
   <div id="projectbrief">NETCONF Library</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.3.1 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li><a href="../../index.html"><span>Main&#160;Page</span></a></li>
      <li class="current"><a href="../../pages.html"><span>Related&#160;Pages</span></a></li>
      <li><a href="../../modules.html"><span>Modules</span></a></li>
      <li><a href="../../annotated.html"><span>Data&#160;Structures</span></a></li>
      <li><a href="../../files.html"><span>Files</span></a></li>
      <li>
        <div id="MSearchBox" class="MSearchBoxInactive">
        <span class="left">
          <img id="MSearchSelect" src="../../search/mag_sel.png"
               onmouseover="return searchBox.OnSearchSelectShow()"
               onmouseout="return searchBox.OnSearchSelectHide()"
               alt=""/>
          <input type="text" id="MSearchField" value="Search" accesskey="S"
               onfocus="searchBox.OnSearchFieldFocus(true)" 
               onblur="searchBox.OnSearchFieldFocus(false)" 
               onkeyup="searchBox.OnSearchFieldChange(event)"/>
          </span><span class="right">
            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="../../search/close.png" alt=""/></a>
          </span>
        </div>
      </li>
    </ul>
  </div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('d3/df0/transapi_tutorial.html','../../');});
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark">&#160;</span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark">&#160;</span>Data Structures</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(2)"><span class="SelectionMark">&#160;</span>Files</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(3)"><span class="SelectionMark">&#160;</span>Functions</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(4)"><span class="SelectionMark">&#160;</span>Variables</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(5)"><span class="SelectionMark">&#160;</span>Typedefs</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(6)"><span class="SelectionMark">&#160;</span>Enumerations</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(7)"><span class="SelectionMark">&#160;</span>Enumerator</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(8)"><span class="SelectionMark">&#160;</span>Macros</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(9)"><span class="SelectionMark">&#160;</span>Groups</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(10)"><span class="SelectionMark">&#160;</span>Pages</a></div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="header">
  <div class="headertitle">
<div class="title">transAPI Tutorial </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>On this page we will show how to write simple module for controlling <a href="http://netconfcentral.org/modulereport/toaster">example toaster</a>. </p>
<dl class="section note"><dt>Note</dt><dd>To install libnetconf follow instruction on <a class="el" href="../../d9/d87/install.html">Compilation and Installation</a> page.</dd></dl>
<h2>Preparations</h2>
<p>First we need to identify important parts of configuration data. Since toaster data model describes only one configurable element we have easy choice. So we can create the 'paths_file' file containing specification of our chosen element and mapping prefixes with URIs for any used namespace.</p>
<p>Our file may look like this (irrespective of order): </p>
<div class="fragment"><div class="line">toaster=http:<span class="comment">//netconfcentral.org/ns/toaster</span></div>
<div class="line">/toaster:toaster</div>
</div><!-- fragment --><p>If we want (we do) to create call back functions for RPC messages defined for toaster we need its data model in YIN format. Data model in YANG format can be downloaded from NETCONF CENTRAL (<a href="http://dld.netconfcentral.org/src/toaster@2009-11-20.yang">http://dld.netconfcentral.org/src/toaster@2009-11-20.yang</a>). Then we convert model in YANG to YIN using <a href="http://code.google.com/p/pyang/">pyang</a>.</p>
<div class="fragment"><div class="line">$ pyang -f yin -o toaster@2009-11-20.yin toaster@2009-11-20.yang</div>
</div><!-- fragment --><h2>Generating code</h2>
<ol type="1">
<li>Create new directory for toaster module: <div class="fragment"><div class="line">$ mkdir toaster &amp;&amp; cd toaster/</div>
</div><!-- fragment --></li>
<li>Run `generator.py': <div class="fragment"><div class="line">$ lnc-creator --name toaster --paths paths_file --model toaster@2009-11-20.yin --with-libxml2</div>
</div><!-- fragment --></li>
</ol>
<h2>Filling up functionality</h2>
<p>Here we show the simplest example of toaster simulating module. It is working but does not deal with multiple access and threads correctly. Better example may be seen in git repository (examples/server/transapi/toaster.c).</p>
<ol type="1">
<li>Open 'toaster.c' file with you favorite editor: <div class="fragment"><div class="line">$ vim toaster.c</div>
</div><!-- fragment --></li>
</ol>
<ol type="1">
<li>Add global variables and auxiliary functions <div class="fragment"><div class="line"><span class="keyword">enum</span> {ON, OFF, BUSY} status;</div>
<div class="line">pthread_t thread;</div>
<div class="line"></div>
<div class="line"><span class="keywordtype">void</span> * auxiliary_make_toast(<span class="keywordtype">void</span> * time)</div>
<div class="line">{</div>
<div class="line">        sleep(*(<span class="keywordtype">int</span>*)time);</div>
<div class="line"></div>
<div class="line">        <span class="keywordflow">if</span> (status == BUSY) {</div>
<div class="line">                status = ON;</div>
<div class="line">                <a class="code" href="../../da/d54/group__notifications.html#ga9641deaca934bcd7ff66ac3ae60fc722" title="Store a new event in the specified stream. Parameters are specific for different events.">ncntf_event_new</a>(-1, <a class="code" href="../../da/d54/group__notifications.html#ggadcf8c532762d57f7d9a5491e6abb9977a1f1e3c2032baf2542b06052243bd42c9">NCNTF_GENERIC</a>, <span class="stringliteral">&quot;&lt;toastDone&gt;&lt;toastStatus&gt;done&lt;/toastStatus&gt;&lt;/toastDone&gt;&quot;</span>);</div>
<div class="line">        }</div>
<div class="line">        <span class="keywordflow">return</span>(NULL);</div>
<div class="line">}</div>
</div><!-- fragment --></li>
<li>Complete 'init()' function with actions that will be run right after module loads and before any other function in module is called. <div class="fragment"><div class="line"><span class="keywordtype">int</span> init()</div>
<div class="line">{</div>
<div class="line">        status = OFF;</div>
<div class="line">        printf(<span class="stringliteral">&quot;Toaster initialized!\n&quot;</span>);</div>
<div class="line">        <span class="keywordflow">return</span>(EXIT_SUCCESS);</div>
<div class="line">}</div>
</div><!-- fragment --></li>
<li>Locate 'close()' function and fill it with actions that will be run just before the module unloads. No other function will be called after 'close()'. <div class="fragment"><div class="line"><span class="keywordtype">void</span> close()</div>
<div class="line">{</div>
<div class="line">        printf(<span class="stringliteral">&quot;Toaster ready for unplugging!\n&quot;</span>);</div>
<div class="line">}</div>
</div><!-- fragment --></li>
<li>Fill 'get_state_data()' function with code that will generate state information as defined in data model. <div class="fragment"><div class="line"><span class="keywordtype">char</span> * get_state_data(<span class="keywordtype">char</span> * model, <span class="keywordtype">char</span> * running, <span class="keyword">struct</span> nc_err **err)</div>
<div class="line">{</div>
<div class="line">        <span class="keywordflow">return</span> strdup(<span class="stringliteral">&quot;&lt;?xml version=&quot;</span>1.0<span class="stringliteral">&quot;?&gt;&lt;toaster xmlns=&quot;</span>http:<span class="comment">//netconfcentral.org/ns/toaster&quot;&gt; ... &lt;/toaster&gt;&quot;);</span></div>
<div class="line">}</div>
</div><!-- fragment --></li>
<li>Complete configuration callbacks. The 'op' parameter may be used to determine operation which was done with the node. Parameter 'node' holds a copy of node after change (or before change if op == XMLDIFF_REM). <div class="fragment"><div class="line"><span class="keywordtype">int</span> callback_toaster_toaster (<a class="code" href="../../d8/d55/group__transapi.html#ga10d59d84527f735d2781dbbb629a4488" title="Enum specifying states of node in document.">XMLDIFF_OP</a> op, xmlNodePtr node, <span class="keywordtype">void</span> ** data)</div>
<div class="line">{</div>
<div class="line">        <span class="keywordflow">switch</span>(op) {</div>
<div class="line">        <span class="keywordflow">case</span> <a class="code" href="../../d8/d55/group__transapi.html#gga10d59d84527f735d2781dbbb629a4488adc0f4fc8354a1e293db5efd4f8e6f0b1">XMLDIFF_ADD</a>:</div>
<div class="line">                status = ON;</div>
<div class="line">                <span class="keywordflow">break</span>;</div>
<div class="line">        <span class="keywordflow">case</span> <a class="code" href="../../d8/d55/group__transapi.html#gga10d59d84527f735d2781dbbb629a4488a149cdeec9d87bdbb700861f773759129">XMLDIFF_REM</a>:</div>
<div class="line">                status = OFF;</div>
<div class="line">                <span class="keywordflow">break</span>;</div>
<div class="line">        <span class="keywordflow">default</span>:</div>
<div class="line">                <span class="keywordflow">return</span>(EXIT_FAILURE);</div>
<div class="line">        }</div>
<div class="line">        <span class="keywordflow">return</span>(EXIT_SUCCESS);</div>
<div class="line">}</div>
</div><!-- fragment --></li>
<li>Fill RPC message callback functions with code that will be run when message arrives. <div class="fragment"><div class="line"><a class="code" href="../../d0/de2/group__reply.html#ga40338a1274759a932a7c2c7b8ed0121d" title="reply message.">nc_reply</a> * rpc_make_toast (xmlNodePtr input[])</div>
<div class="line">{</div>
<div class="line">        xmlNodePtr toasterDoneness = input[0];</div>
<div class="line">     xmlNodePtr toasterToastType = input[1];</div>
<div class="line"></div>
<div class="line">     <a class="code" href="../../d0/de2/group__reply.html#ga40338a1274759a932a7c2c7b8ed0121d" title="reply message.">nc_reply</a> * reply;</div>
<div class="line">     <span class="keywordtype">int</span> doneness = atoi(xmlNodeGetContent(toasterDoneness));</div>
<div class="line"></div>
<div class="line">        <span class="keywordflow">if</span> (status == ON) {</div>
<div class="line">                status = BUSY;</div>
<div class="line">                pthread_create(&amp;thread, NULL, auxiliary_make_toast, (<span class="keywordtype">void</span>*)&amp;doneness);</div>
<div class="line">                pthread_detach(thread);</div>
<div class="line">                reply = <a class="code" href="../../d0/de2/group__reply.html#ga047f565bb3671ec4016fef5461e8f67e" title="Create &lt;ok&gt; rpc-reply response.">nc_reply_ok</a>();</div>
<div class="line">        } <span class="keywordflow">else</span> {</div>
<div class="line">                reply = <a class="code" href="../../d0/de2/group__reply.html#ga12fd89263289491b84398279e0e449fd" title="Create rpc-reply response with &lt;rpc-error&gt; content.">nc_reply_error</a>(<a class="code" href="../../d3/d35/group__gen_a_p_i.html#ga057524ba5256c428b6bf88710f000e0c" title="Create a new error description structure.">nc_err_new</a>(<a class="code" href="../../da/d41/error_8h.html#a170ed93037b65394a05e074400848eb2ae9d2e7a938b0fb4583b961a7079aabe3">NC_ERR_OP_FAILED</a>));</div>
<div class="line">        }</div>
<div class="line">        <span class="keywordflow">return</span>(reply);</div>
<div class="line">}</div>
</div><!-- fragment --> <div class="fragment"><div class="line"><a class="code" href="../../d0/de2/group__reply.html#ga40338a1274759a932a7c2c7b8ed0121d" title="reply message.">nc_reply</a> * rpc_cancel_toast (xmlNodePtr input[])</div>
<div class="line">{</div>
<div class="line">     <a class="code" href="../../d0/de2/group__reply.html#ga40338a1274759a932a7c2c7b8ed0121d" title="reply message.">nc_reply</a> * reply;</div>
<div class="line"></div>
<div class="line">     <span class="keywordflow">if</span> (status == BUSY) {</div>
<div class="line">        status = ON;</div>
<div class="line">        <a class="code" href="../../da/d54/group__notifications.html#ga9641deaca934bcd7ff66ac3ae60fc722" title="Store a new event in the specified stream. Parameters are specific for different events.">ncntf_event_new</a>(-1, <a class="code" href="../../da/d54/group__notifications.html#ggadcf8c532762d57f7d9a5491e6abb9977a1f1e3c2032baf2542b06052243bd42c9">NCNTF_GENERIC</a>, <span class="stringliteral">&quot;&lt;toastDone&gt;&lt;toastStatus&gt;canceled&lt;/toastStatus&gt;&lt;/toastDone&gt;&quot;</span>);</div>
<div class="line">        reply = <a class="code" href="../../d0/de2/group__reply.html#ga047f565bb3671ec4016fef5461e8f67e" title="Create &lt;ok&gt; rpc-reply response.">nc_reply_ok</a>();</div>
<div class="line">     } <span class="keywordflow">else</span> {</div>
<div class="line">        reply = <a class="code" href="../../d0/de2/group__reply.html#ga12fd89263289491b84398279e0e449fd" title="Create rpc-reply response with &lt;rpc-error&gt; content.">nc_reply_error</a>(<a class="code" href="../../d3/d35/group__gen_a_p_i.html#ga057524ba5256c428b6bf88710f000e0c" title="Create a new error description structure.">nc_err_new</a>(<a class="code" href="../../da/d41/error_8h.html#a170ed93037b65394a05e074400848eb2ae9d2e7a938b0fb4583b961a7079aabe3">NC_ERR_OP_FAILED</a>));</div>
<div class="line">     }</div>
<div class="line">     <span class="keywordflow">return</span>(reply);</div>
<div class="line">}</div>
</div><!-- fragment --></li>
</ol>
<h2>Compiling module</h2>
<p>Following sequence of commands will produce shared library 'toaster.so' which may be loaded into libnetconf: </p>
<div class="fragment"><div class="line">$ autoreconf</div>
<div class="line">$ ./configure</div>
<div class="line">$ make</div>
</div><!-- fragment --><h2>Integrating to example server</h2>
<p>In server we use libnetconfs function <a class="el" href="../../d8/d55/group__transapi.html#ga80e69b4cada8c35e5e358287e8af3d85" title="Create new datastore structure with transaction API support.">ncds_new_transapi()</a> instead of <a class="el" href="../../db/d67/group__store.html#ga69009c5985f9eec3a6920f98a6a1a5e6" title="Create a new datastore structure of the specified implementation type.">ncds_new()</a> to create transAPI capable data store. Then you do not need to process any data-writing (edit-config, copy-config, delete-config, lock, unlock) data-reading (get, get-config) and module data model defined RPC operations. All these operation are processed inside <a class="el" href="../../db/d67/group__store.html#ga6e6e979bd82e50913c82b4dc37cb8759" title="Perform the requested RPC operation on the all datastores controlled by the libnetconf (created by nc...">ncds_apply_rpc2all()</a> function. </p>
</div></div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
  <ul>
    <li class="navelem"><a class="el" href="../../d9/d25/transapi.html">Transaction API (transAPI)</a></li>
    <li class="footer">Generated on Tue Sep 24 2013 16:01:43 for libnetconf by
    <a href="http://www.doxygen.org/index.html">
    <img class="footer" src="../../doxygen.png" alt="doxygen"/></a> 1.8.3.1 </li>
  </ul>
</div>
</body>
</html>
